package parser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.TreeBidiMap;
import org.gps.utils.LatLonPoint;

import utils.datetime.DateTime;


public class TwitterParser {
	public String LDAPATH;
	public String CSV;
	public int TIMEINTERVALS;
	public Map<Integer,String> int2filename;
	public Map<String,LatLonPoint> mapPoints;
	public Map<Integer,String> mapTimeIntervals;
	
	public static final String SEPARATOR = "X";
	public static final DecimalFormat D_FORMATTER = new DecimalFormat("00");
	public static final SimpleDateFormat inputFormat = new SimpleDateFormat("dd-MM-yyyy");
	
	public TwitterParser(String path, String csv, int hours) throws Exception{
		this.LDAPATH = path;
		this.CSV = csv;
		this.TIMEINTERVALS = hours;
		
		setMapHours();
		createMapping();
	}
	
	
	public void createDocs(ArrayList<Integer> daysofweek, ArrayList<Integer> months) throws Exception{
		DateTime dtutils = new DateTime();
		
		//delete all files
        File dir = new File(LDAPATH);
        String[] contents = dir.list();
        for(int i=0;i<contents.length;i++)
        	new File(dir,contents[i]).delete();
        
        BufferedReader inFile = new BufferedReader(new FileReader(new File(CSV)));

		String day = "00-00-0000";
		PrintWriter out = null;
		//first line: header
		String line = inFile.readLine();
		while((line = inFile.readLine()) != null){
			String [] data = line.split(",");
			String date = D_FORMATTER.format(Integer.parseInt(data[2]))+"-"+D_FORMATTER.format(Integer.parseInt(data[1]))+"-"+data[0];
			Calendar cal = new GregorianCalendar();
			cal.setTime(inputFormat.parse(date));
			if(!date.equals(day) && daysofweek.contains(cal.get(Calendar.DAY_OF_WEEK)) && months.contains(cal.get(Calendar.MONTH))){
				//this is a new day -> creates a new file
				if(!day.equals("00-00-0000"))//the file must have been initialized
					out.close();
				day = date;
				String filename = dtutils.DayOfWeekTranslator.get(cal.get(Calendar.DAY_OF_WEEK))+","+day;
				
				out = new PrintWriter(new FileWriter(new File(LDAPATH+"\\"+filename+".txt")));	
			}
			
			if(daysofweek.contains(cal.get(Calendar.DAY_OF_WEEK)) && months.contains(cal.get(Calendar.MONTH))){
				String word = getWord(line);
				
				//add for times each word: one for each half-hour
				for(int i=0;i<4;i++)
					out.print(word+"\t");
			}
		}
		out.close();
		
		createDaysMapping();
			
	}
	
	public void createDaysMapping(){
		int2filename = new HashMap<Integer, String>();
		
		//each file contains a day
		//the name of the file is in the form: Mon,dd-MM-yyy.txt
		File fdir = new File(LDAPATH); 
		File[] daysfile = fdir.listFiles();
		int filecounter = 0;
		for(int i=0;i<daysfile.length;i++)
			//to avoid folders created by sourceforge
			if(!daysfile[i].getName().contains("svn")){
				String daypath = daysfile[i].getAbsolutePath();
				//add filename
				int2filename.put(filecounter, daypath.substring(LDAPATH.length(), daypath.length()-".txt".length()));
				filecounter++;
			}
	}
	
	
	public void createMapping() throws Exception{
		mapPoints = new HashMap<String, LatLonPoint>();
		
		BufferedReader inFile = new BufferedReader(new FileReader(new File(CSV)));
		//first line: header
		String line = inFile.readLine();
		while((line = inFile.readLine()) != null){
			String [] data = line.split(",");
			String key = data[4]+"-"+data[5];
			LatLonPoint p = new LatLonPoint(Double.parseDouble(data[7]), Double.parseDouble(data[8]));
			mapPoints.put(key, p);
		}
	}
	
	/*
	 * given a line: 2010,5,27,3,3,7,3,40.7526442530693,-73.9889362550028
	 * this function returns the corresponding word in the following form: hourXiXj
	 */
	public static String getWord(String line){
		String word = "";
		String [] data = line.split(",");
		
		//add hour
		word += hour2word.get(Integer.parseInt(data[3]))+SEPARATOR;
		
		//add i
		char [] indexchar = data[4].toCharArray();
		word += getCharacter(indexchar)+SEPARATOR;
		
		//add j
		indexchar = data[5].toCharArray();
		word += getCharacter(indexchar);
		
		
		return word;
		
	}
	
	public static String getCharacter(char[] integ){
		String ch = "";
		
		for(int i=0;i<integ.length;i++){
			char [] sx = new char[]{integ[i]};
			ch += number2word.get(Integer.parseInt(new String(sx)));
		}
		
		return ch;
		
	}
	
	public static String getPieceWord(String index){
		String lab = "";
		
		char [] indexchar = index.toCharArray();
		
		for(int i=0;i<indexchar.length;i++){
			char [] sx = new char[]{indexchar[i]};
			//System.out.println();
			lab += Integer.toString((Integer)number2word.getKey(new String(sx)));
		}
		
		return lab;
		
	}
	
	/*
	 * given a word hXiXj
	 */
    public static String[] translateWordArray(String word){
    	String [] tranword = new String[3];
    	
    	//0: hour, 1: i, 2: j, 3: #user 
    	String[] token = word.split("X");
    	
		//time index
    	tranword[0] = Integer.toString((Integer)hour2word.getKey(token[0]));
    	
    	//i
    	tranword[1] = getPieceWord(token[1]);
    	
    	//j
    	tranword[2] = getPieceWord(token[2]);
		
    	return tranword;
    }
    
	public Map<Integer,String> getMapHours(){
		return mapTimeIntervals;
	}
	
	public Map<String,LatLonPoint> getMapPoints(){
		return mapPoints;
	}
	
	public Map<Integer,String> getInt2Filename(){
		return int2filename;
	}
	
	public static BidiMap hour2word = new TreeBidiMap();
	static {
		hour2word.put(0,"a");
		hour2word.put(1,"b");
		hour2word.put(2,"c");
		hour2word.put(3,"d");
		hour2word.put(4,"e");
		hour2word.put(5,"f");
		hour2word.put(6,"g");
		hour2word.put(7,"h");	
		hour2word.put(8,"i");	
		hour2word.put(9,"j");	
		hour2word.put(10,"k");	
		hour2word.put(11,"l");
		hour2word.put(12,"m");
		hour2word.put(13,"n");
		hour2word.put(14,"o");
		hour2word.put(15,"p");
		hour2word.put(16,"q");
		hour2word.put(17,"r");
		hour2word.put(18,"s");
		hour2word.put(19,"t");
		hour2word.put(20,"u");
		hour2word.put(21,"v");
		hour2word.put(22,"x");
		hour2word.put(23,"y");
	}
	
	public static BidiMap number2word = new TreeBidiMap();
	static {
		number2word.put(0,"a");
		number2word.put(1,"b");
		number2word.put(2,"c");
		number2word.put(3,"d");
		number2word.put(4,"e");
		number2word.put(5,"f");
		number2word.put(6,"g");
		number2word.put(7,"h");	
		number2word.put(8,"i");	
		number2word.put(9,"l");	
	}
	
	public void setMapHours(){
		mapTimeIntervals = new HashMap<Integer,String>();
		
		if(TIMEINTERVALS == 12){
			//first is 0
			mapTimeIntervals.put(0, "00:00-02:00");
			mapTimeIntervals.put(1, "02:00-04:00");
			mapTimeIntervals.put(2, "04:00-06:00");
			mapTimeIntervals.put(3, "06:00-08:00");
			mapTimeIntervals.put(4, "08:00-10:00");
			mapTimeIntervals.put(5, "10:00-12:00");
			mapTimeIntervals.put(6, "12:00-14:00");
			mapTimeIntervals.put(7, "14:00-16:00");
			mapTimeIntervals.put(8, "16:00-18:00");
			mapTimeIntervals.put(9, "18:00-20:00");
			mapTimeIntervals.put(10, "20:00-22:00");
			mapTimeIntervals.put(11, "22:00-24:00");
		}
		
		if(TIMEINTERVALS == 24){
			//first is 0
			mapTimeIntervals.put(0, "00:00-01:00");
			mapTimeIntervals.put(1, "01:00-02:00");
			mapTimeIntervals.put(2, "02:00-03:00");
			mapTimeIntervals.put(3, "03:00-04:00");
			mapTimeIntervals.put(4, "04:00-05:00");
			mapTimeIntervals.put(5, "05:00-06:00");
			mapTimeIntervals.put(6, "06:00-07:00");
			mapTimeIntervals.put(7, "07:00-08:00");
			mapTimeIntervals.put(8, "08:00-09:00");
			mapTimeIntervals.put(9, "09:00-10:00");
			mapTimeIntervals.put(10, "10:00-11:00");
			mapTimeIntervals.put(11, "11:00-12:00");
			mapTimeIntervals.put(12, "12:00-13:00");
			mapTimeIntervals.put(13, "13:00-14:00");
			mapTimeIntervals.put(14, "14:00-15:00");
			mapTimeIntervals.put(15, "15:00-16:00");
			mapTimeIntervals.put(16, "16:00-17:00");
			mapTimeIntervals.put(17, "17:00-18:00");
			mapTimeIntervals.put(18, "18:00-19:00");
			mapTimeIntervals.put(19, "19:00-20:00");
			mapTimeIntervals.put(20, "20:00-21:00");
			mapTimeIntervals.put(21, "21:00-22:00");
			mapTimeIntervals.put(22, "22:00-23:00");
			mapTimeIntervals.put(23, "23:00-24:00");
		}
		
		if(TIMEINTERVALS == 6){
			//first is 0
			mapTimeIntervals.put(0, "00:00-04:00");
			mapTimeIntervals.put(1, "04:00-08:00");
			mapTimeIntervals.put(2, "08:00-12:00");
			mapTimeIntervals.put(3, "12:00-16:00");
			mapTimeIntervals.put(4, "16:00-20:00");
			mapTimeIntervals.put(5, "20:00-24:00");			
		}	
	}
}
